package com.android.launcher3.util;


import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class ObjectsTools {

    public static boolean equals(Object a, Object b) {
        return (a == b) || (a != null && a.equals(b));
    }

    public static boolean equalsValue(byte[] a, byte[] b) {
        if (a == null && b == null) return true;
        if (a == null ^ b == null) return false;
        if (a.length != b.length) return false;

        for (int i = 0; i < a.length; i++) {
            if (a[i] != b[i]) {
                return false;
            }
        }
        return true;
    }

    /**
     * 继承于该类型的所有子类型中的所有引用类型必须实现 Serializable 接口
     *
     * @return 深克隆，引用类型对象生成新地址
     */
    public static <T extends Serializable> T deepClone(T obj) {
        if (obj == null) {
            return null;
        }
        ObjectOutputStream oos = null;
        ByteArrayOutputStream baos = null;
        ByteArrayInputStream bais = null;
        ObjectInputStream ois = null;
        try {
            //将对象写入流中
            baos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(baos);
            oos.writeObject(obj);

            //将对象从流中取出
            bais = new ByteArrayInputStream(baos.toByteArray());
            ois = new ObjectInputStream(bais);
            return (T) ois.readObject();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //释放
            if (oos != null) {
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (baos != null) {
                try {
                    baos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bais != null) {
                try {
                    bais.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (ois != null) {
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    public static byte[] hex2byte(String hex) {
        if (hex == null || hex.length() == 0) {
            return null;
        }
        try {
            if (hex.length() % 2 != 0) {
                hex = "0" + hex;
            }
            byte[] bytes = new byte[hex.length() / 2];
            for (int i = 0; i < bytes.length; i++) {
                String s = hex.substring(i * 2, i * 2 + 2);
                System.out.println(s);
                bytes[i] = (byte) (0xff & Integer.parseInt(s, 16));

            }
            return bytes;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String byte2hex(byte[] b) {
        return byte2hex(b, false);
    }

    public static String byte2hex(byte[] b, boolean reverse) {
        if (b == null) {
            return "";
        }
        StringBuilder hs = new StringBuilder();
        String stmp;
        if (reverse) {
            for (int n = b.length - 1; n >= 0; n--) {
                try {
                    stmp = Integer.toHexString(b[n] & 0xff);
                    if (stmp.length() == 1) {
                        hs.append("0").append(stmp);
                    } else {
                        hs.append(stmp);
                    }
                } catch (Exception e) {
                    hs.append("00");
                }
            }
        } else {
            for (int n = 0; n < b.length; n++) {
                try {
                    stmp = Integer.toHexString(b[n] & 0xff);
                    if (stmp.length() == 1) {
                        hs.append("0").append(stmp);
                    } else {
                        hs.append(stmp);
                    }
                } catch (Exception e) {
                    hs.append("00");
                }

            }
        }

        return hs.toString().toUpperCase();
    }

    /**
     * @param big 大端高位在前，小端低位在前
     */
    public static int byte2Int(byte[] bytes, boolean big) {
        if (bytes == null) {
            return 0;
        }
        if (bytes.length > 4) {
            byte[] temp = bytes;
            if (big) {
                bytes = new byte[4];
                System.arraycopy(temp, temp.length - 4, bytes, 0, bytes.length);
            } else {
                bytes = new byte[]{temp[0], temp[1], temp[2], temp[3]};
            }
        }
        int val = 0;
        int by;
        for (int i = 0; i < bytes.length; i++) {
            by = bytes[i] & 0xFF;
            if (big) {
                val |= by << (8 * (bytes.length - 1 - i));
            } else {
                val |= by << (8 * i);
            }
        }
        return val;
    }

    /**
     * @param big     大端高位在前，小端低位在前
     * @param autoLen 自动长度,去掉为0的数据
     */
    public static byte[] numb2bytes(Number val, boolean big, boolean autoLen) {
        if (val instanceof Byte) {
            return new byte[]{val.byteValue()};
        }
        int bit;
        long value;
        if (val instanceof Short) {
            bit = Short.SIZE / 8;
            value = val.shortValue();
        } else if (val instanceof Integer) {
            bit = Integer.SIZE / 8;
            value = val.intValue();
        } else if (val instanceof Long) {
            bit = Long.SIZE / 8;
            value = val.longValue();
        } else if (val instanceof Float) {
            bit = Float.SIZE / 8;
            value = (int) val.floatValue();
        } else if (val instanceof Double) {
            bit = Double.SIZE / 8;
            value = (long) val.doubleValue();
        } else {
            return new byte[0];
        }
        byte[] res = new byte[bit];
        byte temp;
        int index = 0;
        while (index < bit) {
            if (value <= 0) {
                break;
            }
            temp = (byte) (value & 0xff);
            if (big) {
                res[res.length - 1 - index] = temp;
            } else {
                res[index] = temp;
            }
            value >>= 8;
            index++;
        }

        if (autoLen) {
            bit = 0;//start
            index = res.length;//end
            if (big) {
                for (int i = 0; i < res.length; i++) {
                    if (res[i] == 0) {
                        bit++;
                    } else {
                        break;
                    }
                }
            } else {
                for (int i = res.length - 1; i >= 0; i--) {
                    if (res[i] == 0) {
                        index--;
                    } else {
                        break;
                    }
                }
            }
            if (bit != 0 || index != res.length) {
                byte[] resTemp = res;
                res = new byte[index - bit];
                System.arraycopy(resTemp, bit, res, 0, res.length);
            }
        }

        return res;
    }

    public static String byte2ASCLL(byte[] b) {
        if (b == null) {
            return "";
        }
        StringBuilder hs = new StringBuilder();
        for (int n = 0; n < b.length; n++) {
            hs.append((char) b[n]);
        }
        return hs.toString();
    }

    public static int getHexlarge(byte[] bytes, boolean reverse) {
        if (bytes == null || bytes.length == 0) {
            return 0;
        }
        int large = 0;
        int wei, byteValue;

        for (int i = 0; i < bytes.length; i++) {
            if (reverse) {
                wei = 8 * i;
            } else {
                wei = 8 * (bytes.length - i - 1);
            }
            byteValue = bytes[i];
            if (byteValue < 0) {
                byteValue += 256;
            }
            large += byteValue << wei;
        }
        return large;
    }

    public static int getHexlarge(int[] bytes, boolean reverse) {
        if (bytes == null || bytes.length == 0) {
            return 0;
        }
        int large = 0;
        int wei;

        for (int i = 0; i < bytes.length; i++) {
            if (reverse) {
                wei = 8 * i;
            } else {
                wei = 8 * (bytes.length - i - 1);
            }
            large += bytes[i] << wei;
        }
        return large;
    }


    /**
     * 找到数据中的报头或报尾
     *
     * @param data     数据
     * @param find     要找的数据
     * @param findHead true：find数据作为报头，false：报尾
     * @param expect   当未找到时，是否保留当前数据并期望之后能找到
     * @return 0:返回数据；1:判断是否找到，null:未找到,byte[0]:找到了
     */
    public static byte[][] findHeadTail(byte[] data, byte[] find, boolean findHead, boolean expect) {
        if (data == null || data.length == 0) {
            return new byte[][]{data, null};
        }
        if (find == null || find.length == 0) {
            if (expect) {
                return new byte[][]{data, null};
            } else {
                return new byte[][]{null, null};
            }
        }
        int removeIndex = 0;
        int dIndex = 0;
        int fIndex = 0;
        byte d, f;//
        boolean findout = true;
        while (dIndex < data.length) {
            findout = true;
            d = data[dIndex];
            while (fIndex < find.length) {

                f = find[fIndex];

                if (d == f) {
                    if (dIndex + fIndex + 1 >= data.length) {
                        if (fIndex + 1 < find.length) {
                            findout = expect;
                        }
                        break;
                    }
                    d = data[dIndex + fIndex + 1];
                    fIndex++;
                } else {
                    findout = false;
                    break;
                }
            }
            fIndex = 0;
            dIndex++;
            if (findout) {
                break;
            }
            removeIndex = dIndex;
        }
        if (!expect && !findout) {
            return new byte[][]{null, null};
        }

        int start, length;
        if (findHead) {
            length = data.length - removeIndex;
            if (length < 0) {
                length = 0;
            }
            start = removeIndex;
        } else {
            length = removeIndex + find.length;
            if (length > data.length) {
                length = data.length;
            }
            start = 0;
        }
        if (length == 0) {
            return new byte[][]{null, null};
        }
        byte[] res = new byte[length];
        System.arraycopy(data, start, res, 0, length);
        return new byte[][]{res, findout ? new byte[0] : null};
    }

    public static void main(String[] a) {
        System.out.println(getHexlarge(new byte[]{0x1F, 4}, true));
    }
}
